package com.tmt.im.service.service;

import com.tmt.im.common.enums.IMAuthorityEnum;
import com.tmt.im.common.pojo.*;
import com.tmt.im.service.helper.IgniteQueryHelper;
import lombok.Getter;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.IgniteMessaging;
import org.apache.ignite.cache.query.FieldsQueryCursor;
import org.apache.ignite.cache.query.SqlFieldsQuery;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.util.CollectionUtils;

import java.security.Principal;
import java.text.MessageFormat;
import java.util.List;

/**
 * @Description TODO
 * @Author wuyi
 * @Date 2024/8/12 16:02
 * @Version 1.0
 **/
@Getter
public class BaseService {

    protected final Ignite ignite;

    protected final IgniteCache<Long, ChatSessionPoJo> sessionCache;

    protected final IgniteCache<SessionMemberKey, ChatSessionMemberPoJo> sessionMemberCache;

    protected final IgniteCache<Long, MemberStatusPoJo> sessionMemberStatus;

    protected final IgniteCache<ChatDataKey, ChatDataPoJo> chatDataCache;

    protected final IgniteCache<Long, IMUserPoJo> userCache;

    protected final IgniteCache<Long, PersonalSettingPoJo> userSettingCache;

    protected final IgniteCache<IMFriendKey, IMFriendPoJo> friendCache;

    protected final IgniteCache<BlackBillKey, BlackBillPoJo> blackBillCache;

    protected final IgniteMessaging igniteMessaging;

    public BaseService(Ignite ignite) {
        this.ignite = ignite;

        userCache = ignite.cache(IMUserPoJo.CACHE_NAME);
        assert userCache != null;

        sessionCache = ignite.cache(ChatSessionPoJo.CACHE_NAME);
        assert sessionCache != null;

        sessionMemberCache = ignite.cache(ChatSessionMemberPoJo.CACHE_NAME);
        assert sessionMemberCache != null;

        sessionMemberStatus = ignite.cache(MemberStatusPoJo.CACHE_NAME);
        assert sessionMemberStatus != null;

        chatDataCache = ignite.cache(ChatDataPoJo.CACHE_NAME);
        assert chatDataCache != null;

        userSettingCache = ignite.cache(PersonalSettingPoJo.CACHE_NAME);
        assert userSettingCache != null;

        friendCache = ignite.cache(IMFriendPoJo.CACHE_NAME);
        assert friendCache != null;

        blackBillCache = ignite.cache(BlackBillPoJo.CACHE_NAME);
        assert blackBillCache != null;

        igniteMessaging = ignite.message(ignite.cluster().forRemotes());
    }

    /**
     * 是否是群主。
     *
     * @param sessionPoJo
     * @return
     */
    public boolean isSessionOwner(Long currentUserId, ChatSessionPoJo sessionPoJo) {
        return sessionPoJo.getOwnerId().equals(currentUserId);
    }

    public boolean isManager(Long currentUserId, Long sessionId) {
        String sql = MessageFormat.format("select * from {0} where memberId=? and sessionId=?",
                ChatSessionMemberPoJo.CACHE_NAME);
        ChatSessionMemberPoJo memberPoJo = IgniteQueryHelper.findOneBy(sql, new Object[]{currentUserId, sessionId},
                ChatSessionMemberPoJo.class, sessionMemberCache);
        return memberPoJo != null && memberPoJo.getRoleInSession() == 2;
    }

    /**
     * 是否有足够权限。
     *
     * @param principal
     * @param authorityEnums
     * @return
     */
    public boolean hasAuthenticated(Principal principal, List<IMAuthorityEnum> authorityEnums) {
        if (principal instanceof JwtAuthenticationToken token) {
            //查询是否具备权限
            List<String> authorities = token.getToken().getClaim("authorities");
            return !CollectionUtils.isEmpty(authorityEnums)
                    && authorityEnums.stream().anyMatch(x -> authorities.contains(x.name()));
        }
        return false;
    }

    /**
     * 当前用户是否在群组中。
     *
     * @param currentUserId
     * @param sessionPoJo
     * @return
     */
    public boolean inSession(Long currentUserId, ChatSessionPoJo sessionPoJo) {
        //查询当前用户是否在目标群组中。
        String sql = MessageFormat.format("select * from {0} where memberId = ? and sessionId = ? and agreeStatus = ?",
                ChatSessionMemberPoJo.CACHE_NAME);
        SqlFieldsQuery query = new SqlFieldsQuery(sql).setArgs(currentUserId, sessionPoJo.getId(), 1);
        List<?> list = null;
        try (FieldsQueryCursor<List<?>> cursor = sessionMemberCache.query(query)) {
            list = cursor.getAll();
        }
        return !CollectionUtils.isEmpty(list);
    }

}
